<script setup lang="ts">
import {onMounted, watch, ref, nextTick, Component, unref, shallowRef} from 'vue';
import TreeItem from "@/views/popup/TreeItem.vue";
import {Bookmark, BookmarkObj, cleanupBookmarks, dumpBookmarksJSON, loadBookmarksJSON} from "@/utils/bookmarkUtils";
import {ArrowUpBold, Fold, More, Search} from '@element-plus/icons-vue'
import {initBrowserError, PageState, popupPageStatStoreKey, bookmarkStoreKey} from "@/utils/constants";
import {browserDriver, config} from "@/store/modules/globals";

const bookmark = ref<Bookmark[]>([]);
const activeName = shallowRef("bookmark");
const defaultProps = {
  children: 'children',
  label: 'title'
};
const defaultExpandedKeys = ref<string[]>([]);
const expandedKeysSet = ref<Set<string>>(new Set<string>());
const filterText = shallowRef('');
const tree = ref<any>(null);
const affixOffset = shallowRef(0);
const affixMarginLeft = shallowRef(0);
const popoverRef = ref();
const buttonRef = ref();
const popupCardTabBookmark = ref();
const isShowBackTop = shallowRef(false);

if (
    !browserDriver.getBookmarkTree || !browserDriver.openUrl || !browserDriver.openExtensionUrl
    || !browserDriver.restoreStorageToObject || !browserDriver.storeObjectToStorage
) {
  throw initBrowserError;
}
const getBookmarkTree = browserDriver.getBookmarkTree;
const openUrl = browserDriver.openUrl;
const openExtensionUrl = browserDriver.openExtensionUrl;
const restoreStorageToObject = browserDriver.restoreStorageToObject;
const storeObjectToStorage = browserDriver.storeObjectToStorage;


/**
 * 从浏览器中加载书签
 */
function loadBookmarkFromBrowser() {
  bookmark.value = [];
  getBookmarkTree().then((bookmarkTree: Bookmark[]) => {
    bookmark.value.push(...bookmarkTree);
    // console.log("popup bookmark", bookmark);
  });
}

/**
 * 打开插件网址
 * @param data
 */
function clickOpenUrl(data: Bookmark) {
  if (data.url) {
    openUrl(data.url, config.urlOpenType.value);
  }
}

/**
 * 过滤收藏夹
 * @param value
 * @param data
 */
function filterNode(value: string, data: Bookmark) {
  if (!value) return true;
  if (data.url && data.url.indexOf(value) !== -1) return true;
  return data.title.indexOf(value) !== -1;
}

/**
 * 切换标签
 * @param tab
 * @param event
 */
function clickTab(tab: any, event: any) {
  // console.log(tab, event);
}

/**
 * 点击首页
 */
function clickHome() {
  openExtensionUrl();
}

/**
 * 点击一键整理书签
 */
function clickCleanupBookmarks() {
  let pathSet = {};
  if (!bookmark.value) {
    console.log("收藏夹为空。")
    return
  }
  let parent = null;
  if (bookmark.value.length && bookmark.value[0].parent) {
    parent = bookmark.value[0].parent;
  }
  let newBookmark = cleanupBookmarks(bookmark.value, pathSet,  parent);
  bookmark.value = [...newBookmark];
  checkIsShowBackTopState();
}

/**
 * 折叠树
 */
function collapseTree() {
  // 收起树
  console.log("收起树");
  // expandedKeys.value = [];
  let nodes = tree.value.store._getAllNodes();
  nodes.forEach((item: { expanded: boolean }) => {
    item.expanded = false;
  });
  expandedKeysSet.value.clear();
  checkIsShowBackTopState();
}

/**
 * 恢复页面状态
 */
async function restorePageState(): Promise<boolean> {
  const pageState: PageState | null = await restoreStorageToObject(popupPageStatStoreKey);
  // console.log("pageState", pageState);
  if (!pageState) {
    return false
  }
  else if (!pageState.bookmark) {
    return false;
  }
  // bookmark.value = pageState.bookmark.map(children => Bookmark.fromObject(children))
  let storeBookmark = [];
  if (typeof pageState.bookmark == "string") {
    storeBookmark = loadBookmarksJSON(pageState.bookmark);
  }
  else {
    storeBookmark = pageState.bookmark.map((bm: BookmarkObj) => {return Bookmark.fromObject(bm)});
  }
  bookmark.value = storeBookmark;
  nextTick(() => {
    if (pageState.filterText) {
      filterText.value = pageState.filterText;
    }
  }).then(r => {});
  if (pageState.defaultExpandedKeys) {
    defaultExpandedKeys.value = [...pageState.defaultExpandedKeys];
    pageState.defaultExpandedKeys.forEach((key) => {
      expandedKeysSet.value.add(key);
    });
  }
  return true;
}

/**
 * 保存页面状态
 */
function savePageState() {
  let saveBookmark = dumpBookmarksJSON(bookmark.value);
  let saveDefaultExpandedKeys = [...expandedKeysSet.value];
  const pageState: PageState = {
    bookmark: saveBookmark,
    filterText: filterText.value,
    defaultExpandedKeys: saveDefaultExpandedKeys,
  };
  // console.log("保存pageState", pageState);
  storeObjectToStorage(popupPageStatStoreKey, pageState);
}

/**
 * 节点展开事件
 * @param obj
 * @param node
 * @param component
 */
function nodeExpand(obj: Bookmark, node: any, component: Component) {
  expandedKeysSet.value.add(obj.path);
  // console.log("nodeExpand expandedKeysSet", expandedKeysSet.value);
  savePageState();
}

/**
 * 节点折叠事件
 * @param obj
 * @param node
 * @param component
 */
function nodeCollapse(obj: Bookmark, node: any, component: Component) {
  expandedKeysSet.value.delete(obj.path);
  let needDelKeys = [];
  for (let key of expandedKeysSet.value) {
    // console.log("key", key);
    if (key.startsWith(obj.path)) {
      needDelKeys.push(key);
    }
  }
  for (let key of needDelKeys) {
    expandedKeysSet.value.delete(key);
  }
  // console.log("nodeCollapse expandedKeysSet", expandedKeysSet.value);
  savePageState();
}

/**
 * 返回顶部
 */
function backTop() {
  // console.log("popupCardTabBookmark.value.$el", popupCardTabBookmark.value.$el);
  popupCardTabBookmark.value.$el.scrollTo({top:0, behavior: "smooth"});
}

/**
 * 检查是否显示回到顶部变量状态
 */
function checkIsShowBackTopState() {
  // console.log("popupCardTabBookmark.value.$el.scrollTop：", popupCardTabBookmark.value.$el.scrollTop);
  isShowBackTop.value = (popupCardTabBookmark.value.$el.scrollTop > 200);
}

onMounted(async () => {
  console.log("popup mounted");
  // console.log("config.isStoreBookmarkExpandStatus", config.isStoreBookmarkExpandStatus);
  if (config.isStoreBookmarkExpandStatus.value) {
    const restorePageStateSuccess = await restorePageState();
    if (!restorePageStateSuccess) {
      console.log("恢复页面状态未成功。");
      loadBookmarkFromBrowser();
    }
    window.addEventListener('beforeunload', savePageState);
  }
  else {
    loadBookmarkFromBrowser();
  }
  // 计算固钉位置
  affixOffset.value = tree.value.$el.offsetHeight * 0.1;
  affixMarginLeft.value = tree.value.$el.offsetWidth - 40 - 20;
});

watch(filterText, (val) => {
  if (tree.value) {
    // console.log("val", val);
    tree.value.filter(val);
    if (!val && config.isCollapsedWhenBookmarkTreeNullSearch.value) {
      collapseTree();
    }
  }
});
watch(bookmark, (new_value, old_value) => {
  // console.log("new_value", new_value);
  // console.log("old_value", old_value);
}, { deep: true });
</script>

<template>
  <el-container id="popup">
    <el-header class="popup-header">
      <div class="popup-header-left">
        <i class="project-logo"></i>
        <span class="project-name">书签管理器</span>
      </div>
      <div class="popup-header-right">
<!--        <el-button @click="loadBookmarkFromBrowser">清理store</el-button>-->
        <el-button @click="clickCleanupBookmarks">一键整理</el-button>
        <el-button @click="clickHome">首页</el-button>
      </div>
    </el-header>
    <el-divider class="popup-divider"></el-divider>
    <el-main class="popup-main">
      <el-tabs class="popup-card-tabs" type="border-card" v-model="activeName" @tab-click="clickTab">
        <el-tab-pane
            class="popup-card-tab-bookmark"
            label="收藏夹"
            name="bookmark"
            ref="popupCardTabBookmark"
            @scroll="checkIsShowBackTopState"
        >
          <div class="bookmark-box">
            <el-input
                class="bookmark-filter"
                placeholder="输入关键字进行过滤"
                v-model="filterText"
                clearable
                :prefix-icon="Search"
            >
            </el-input>
            <el-tree
                class="popup-bookmark-tree"
                :data="bookmark"
                :props="defaultProps"
                @node-click="clickOpenUrl"
                :filter-node-method="filterNode"
                ref="tree"
                node-key="path"
                @node-expand="nodeExpand"
                @node-collapse="nodeCollapse"
                :default-expanded-keys="defaultExpandedKeys"
            >
              <template #default="{node, data}">
                <tree-item :item-data="data" :tree-node="node"></tree-item>
              </template>
            </el-tree>
            <el-affix
                class="tree-collapse-button-affix"
                :style="{marginLeft: `${affixMarginLeft}px`}"
                position="bottom"
                target=".popup-card-tab-bookmark"
                :offset="20"
                v-if="((expandedKeysSet.size > 0) || isShowBackTop) && config.isShowAffix.value"
            >
              <el-button
                  type="primary"
                  circle
                  :icon="More"
                  ref="buttonRef"
              ></el-button>
              <el-popover
                  ref="popoverRef"
                  :virtual-ref="buttonRef"
                  trigger="hover"
                  title=""
                  virtual-triggering
                  persistent
                  :show-arrow="false"
                  placement="left"
                  :popper-style="{
                    background: `rgba(0, 0, 0, 0)!important`,
                    border: 0,
                    boxShadow: `rgba(0, 0, 0, 0) 0 0 0`,
                    padding: 0,
                    minWidth: `32px`,
                    width: `auto`
                  }"
              >
                <el-tooltip
                  placement="top"
                  effect="popover-btn-tips"
                  content="收起"
                >
                  <el-button type="primary" circle :icon="Fold" @click="collapseTree" v-if="expandedKeysSet.size > 0"></el-button>
                </el-tooltip>
                <el-tooltip
                  placement="top"
                  effect="popover-btn-tips"
                  content="回到顶部"
                >
                  <el-button type="primary" circle :icon="ArrowUpBold" @click="backTop" v-if="isShowBackTop"></el-button>
                </el-tooltip>
              </el-popover>

            </el-affix>
          </div>
        </el-tab-pane>
      </el-tabs>
    </el-main>
  </el-container>
</template>


<style scoped>
body {
  max-height: 600px;
}
</style>
<style>
#app {
  height: auto!important;
  min-height: 400px;
  max-height: 600px;
}
#popup {
  width: 480px;
  min-height: 400px;
  max-height: 600px;
}
.popup-divider {
  margin: 0!important;
}
.popup-header {
  height: 40px!important;
  display: flex;
  align-items: center;
  justify-content: space-between;
  user-select: none;
}
.popup-header-left {
  display: flex;
  align-items: center;
}
.popup-header-right {
  display: flex;
  align-items: center;
  justify-content: flex-end;
}
.project-logo {
  width: 20px;
  height: 20px;
  margin-left: 5px;
  background-image: url('@/assets/img/32x32.png');
  background-size: contain;
  display: inline-block;
}
.project-name {
  font-size: 14px;
  font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, SimSun, sans-serif;
  font-weight: 800;
}
.popup-main {
  padding: 5px!important;
  display: flex!important;
  flex-direction: column;
  overflow-x: hidden!important;
}
.popup-card-tabs {
  width: 100%;
  height: 100%;
  flex-grow: 1;
  overflow-y: auto;
}
.el-tabs__content {
  /* overflow: auto!important; */
  padding: 0!important;
}
.tree-collapse-button-affix {
  width: 32px;
}
.popup-card-tab-bookmark {
  /*
  flex-grow: 1;
  display: flex;
  flex-direction: column;
    */
  height: 100%;
  overflow: auto!important;
  padding: 15px;
}
.bookmark-box {
  flex-grow: 1;
  display: flex;
  flex-direction: column;
}
.el-popper.is-popover-btn-tips {
  padding: 3px 12px;
  background: linear-gradient(90deg, rgb(159, 229, 151), rgb(204, 229, 129));
  user-select: none;
}
.el-popper.is-popover-btn-tips .el-popper__arrow::before {
  background: linear-gradient(45deg, #b2e68d, #bce689);
  right: 0;
}
</style>